/**
 * 
 */
package com.yunyike.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.yunyike.constants.CartConstants;
import com.yunyike.constants.CommonConstant;
import com.yunyike.constants.EnumPromotionType;
import com.yunyike.constants.OrderConstants;
import com.yunyike.constants.PromotionConstants;
import com.yunyike.dto.cart.CartDTO;
import com.yunyike.dto.cart.CartMerchandise;
import com.yunyike.dto.cart.CartPromotion;
import com.yunyike.dto.cart.CartPromotionGroup;
import com.yunyike.dto.cart.CartShop;
import com.yunyike.dto.cart.CartShopGroup;
import com.yunyike.exception.BadRequestException;
import com.yunyike.exception.BusinessException;
import com.yunyike.model.Merchandise;
import com.yunyike.model.Promotion;
import com.yunyike.model.PromotionMerchandiseMapping;
import com.yunyike.model.Rule;
import com.yunyike.model.Shop;
import com.yunyike.model.Stock;
import com.yunyike.model.User;
import com.yunyike.redis.JedisManager;
import com.yunyike.service.ICartService;
import com.yunyike.service.IMerchandiseService;
import com.yunyike.service.IPromotionMerchandiseMappingService;
import com.yunyike.service.IPromotionService;
import com.yunyike.service.IRuleService;
import com.yunyike.service.IShopService;
import com.yunyike.service.IStockService;

/**
 * @author zhengqiang.shi
 * 2015年11月22日 上午1:31:02
 */
@Service("CartServiceImpl")
@SuppressWarnings("unchecked")
public class CartServiceImpl implements ICartService {

	private static Logger log = LoggerFactory.getLogger(CartServiceImpl.class);
	
	@Autowired
	private IMerchandiseService merchandiseService;
	
	@Autowired
	private IStockService stockService;
	
	@Autowired
	private IShopService shopService;
	
	@Autowired
	private IPromotionMerchandiseMappingService pmmService;
	
	@Autowired
	private IPromotionService promotionService;
	
	@Autowired
	private IRuleService ruleService;
	
	/**
	 * 添加购物车
	 */
	public int addCart(User user,String merchandiseId,int qty) {
		
		log.info("----->> start to add cart ,param:{},{}.",merchandiseId,qty);
		
		// Redis key
		String cartKey = CartConstants.cartKey(user);
		log.info("cart key:"+cartKey);
		
		// 商品信息
		Merchandise merchandise = merchandiseService.findMerchandiseById(merchandiseId);
		if(merchandise == null){
			throw new BusinessException("Merchandise not fount.");
		}
		
		// 获取当前购物车信息
		List<CartMerchandise> cartMerchandises = (List<CartMerchandise>)JedisManager.getObject(cartKey);
		if(cartMerchandises == null){
			log.info("no data in redis.");
			cartMerchandises = new ArrayList<CartMerchandise>();
		}
		
		// 当前购物车是否存在该商品
		CartMerchandise cartMerchandise = findCartMerchandiseById(cartMerchandises, merchandiseId);
		
		// 添加
		if(cartMerchandise == null){
			log.info("no exist , add...");
			cartMerchandise = new CartMerchandise();
			cartMerchandise.setMerchandiseQty(qty);
			// 设置商品信息
			setMerchandise(cartMerchandises, cartMerchandise, merchandise);
		}else{
			log.info("exist , update...");
			cartMerchandise.setMerchandiseQty(cartMerchandise.getMerchandiseQty()+qty);
		}
		
		// 库存信息
		Map<String, Stock> stockMap = getStock(Arrays.asList(merchandiseId));
		
		// 检查库存
		int checkStock = checkStock(stockMap, cartMerchandise);
		if(CommonConstant.NUMBER_1 != checkStock){
			return checkStock;
		}
		
		// 放入缓存
		log.info("end to add cart.set to redis.");
		JedisManager.setObject(cartKey, CartConstants.CART_OUT_TIME, cartMerchandises);
		
		return CommonConstant.NUMBER_1;
	}

	private Map<String, Stock> getStock(List<String> merchandises) {
		return stockService.getStock(merchandises);
	}

	private int checkStock(Map<String, Stock> stockMap, CartMerchandise cartMerchandise){
		
		if(stockMap == null || stockMap.get(cartMerchandise.getMerchandiseId()) == null){
			log.info("stock info not fount.");
			return CommonConstant.NUMBER_2;
		}
		
		Stock stock = stockMap.get(cartMerchandise.getMerchandiseId());
		// 当前库存
		Integer stockQty = stock.getStockQty();
		// 预扣库存
		Integer stockPreSubQty = stock.getStockPreSubQty();
		// 实际库存 = 库存 - 预扣
		stockQty -= stockPreSubQty;
		
		Integer merchandiseQty = cartMerchandise.getMerchandiseQty();
		if(merchandiseQty > stockQty){
			log.info("out of stock.stock:{},qty:{}",stockQty,merchandiseQty);
			return CommonConstant.NUMBER_2;
		}
		
		cartMerchandise.setMerchandiseStockQty(stockQty);
		
		return CommonConstant.NUMBER_1;
	}
	
	private void setMerchandise(List<CartMerchandise> cartMerchandises,CartMerchandise cartMerchandise,Merchandise merchandise){
		
		cartMerchandise.setMerchandiseId(merchandise.getMerchandiseId());
		cartMerchandise.setMerchandiseNameCn(merchandise.getMerchandiseNameCn());
		cartMerchandise.setMerchandiseNumber(merchandise.getMerchandiseNumber());
		cartMerchandise.setMerchandisePrice(merchandise.getMerchandisePrice());
		cartMerchandise.setMerchandiseDomesticPrice(merchandise.getMerchandiseDomesticPrice());
		cartMerchandise.setMerchandiseIcon(merchandise.getMerchandiseIcon());
		cartMerchandise.setMerchandiseSpec(merchandise.getMerchandiseSpec());
		
		cartMerchandises.add(cartMerchandise);
	}
	
	private CartMerchandise findCartMerchandiseById(List<CartMerchandise> cartMerchandises,String merchandiseId){
		
		for (CartMerchandise cartMerchandise : cartMerchandises) {
			
			String curMerchandiseId = cartMerchandise.getMerchandiseId();
			if(curMerchandiseId.equals(merchandiseId)){
				log.info("exist CartMerchandise.");
				return cartMerchandise;
			}
		}
		
		return null;
	}

	/**
	 * 购物车商品更新数量
	 */
	public int updateCart(User user, String merchandiseId, int qty) {
		log.info("update cart ,param:{}{}",merchandiseId,qty);
		// Redis key
		String cartKey = CartConstants.cartKey(user);
		log.info("cart key:"+cartKey);
		
		// 获取当前购物车信息
		List<CartMerchandise> cartMerchandises = (List<CartMerchandise>)JedisManager.getObject(cartKey);
		if(cartMerchandises == null || cartMerchandises.isEmpty()){
			throw new BusinessException("no data in redis.");
		}
		
		CartMerchandise cartMerchandise = findCartMerchandiseById(cartMerchandises, merchandiseId);
		if(cartMerchandise == null){
			throw new BusinessException("no found "+merchandiseId+" in redis.");
		}
		
		cartMerchandise.setMerchandiseQty(qty);
		
		// 库存信息
		Map<String, Stock> stockMap = getStock(Arrays.asList(merchandiseId));
		
		// 检查库存
		int checkStock = checkStock(stockMap, cartMerchandise);
		if(CommonConstant.NUMBER_1 != checkStock){
			return checkStock;
		}
		
		// 放入缓存
		log.info("end to add cart.set to redis.");
		JedisManager.setObject(cartKey, CartConstants.CART_OUT_TIME, cartMerchandises);
		
		return CommonConstant.NUMBER_1;
		
	}

	/**
	 * 获取购物车信息
	 */
	public CartDTO getCart(User user) {
		// Redis key
		String cartKey = CartConstants.cartKey(user);
		log.info("cart key:"+cartKey);
		
		// 获取当前购物车信息
		List<CartMerchandise> cartMerchandises = (List<CartMerchandise>)JedisManager.getObject(cartKey);
		if(cartMerchandises == null || cartMerchandises.isEmpty()){
			log.info("no data in redis.");
			return null;
		}
		
		// 库存信息
		setStock(cartMerchandises);
		
		// 店铺信息
		setShop(cartMerchandises);
		
		// 活动信息
		setPromotion(cartMerchandises);
		
		// 分组信息
		CartDTO cartDTO = setGroup(cartMerchandises);
		
		// 设置价格
		setPrice(cartDTO);
		
		return cartDTO;
	}

	/**
	 * 购物车删除指定的商品
	 */
	public int removeCart(User user, List<String> merchandiseIds) {
		
		// Redis key
		String cartKey = CartConstants.cartKey(user);
		log.info("cart key:"+cartKey);
		
		// 获取当前购物车信息
		List<CartMerchandise> cartMerchandises = (List<CartMerchandise>)JedisManager.getObject(cartKey);
		if(cartMerchandises == null || cartMerchandises.isEmpty()){
			throw new BadRequestException("no data in redis.delete data failed.");
		}
		
		for (String merchandiseId : merchandiseIds) {
			CartMerchandise cartMerchandise = findCartMerchandiseById(cartMerchandises, merchandiseId);
			if(cartMerchandise == null){
				log.info("merchandiseId:{} not found in redis.",merchandiseId);
				continue;
			}
			
			log.info("merchandiseId:{} remove success.",merchandiseId);
			cartMerchandises.remove(cartMerchandise);
		}
		
		// 放入缓存
		log.info("end to execute remove cart.set to redis.");
		JedisManager.setObject(cartKey, CartConstants.CART_OUT_TIME, cartMerchandises);
		
		return CommonConstant.NUMBER_1;
	}
	
	/**
	 * 获取购物车的商品数量
	 */
	public int cartQty(User user,boolean isSelect) {
		// Redis key
		String cartKey = CartConstants.cartKey(user);
		log.info("cart key:"+cartKey);
		
		// 获取当前购物车信息
		List<CartMerchandise> cartMerchandises = (List<CartMerchandise>)JedisManager.getObject(cartKey);
		if(cartMerchandises == null || cartMerchandises.isEmpty()){
			log.info("no data in redis.");
			return 0;
		}
		
		return merchandisesQty(cartMerchandises,isSelect ? Arrays.asList(true):Arrays.asList(true,false));
		
	}
	
	private void setPrice(CartDTO cartDTO){
		// 购物车总金额
		BigDecimal totalPrice = new BigDecimal(0);
		// 购物车总商品金额
		BigDecimal totalMerchandisesPrice = new BigDecimal(0);
		// 购物车总优惠金额
		BigDecimal totalDiscountPrice = new BigDecimal(0);
		// 购物车总运费
		BigDecimal totalFreightPrice = new BigDecimal(0);
		
		List<CartShopGroup> cartShopGroups = cartDTO.getCartShopGroups();
		
		for (CartShopGroup cartShopGroup : cartShopGroups) {
			// 店铺总商品金额
			BigDecimal shopMerchandisesPrice = new BigDecimal(0);
			// 店铺总优惠金额
			BigDecimal shopDiscountPrice = new BigDecimal(0);
			// 店铺运费
			BigDecimal shopFreightPrice = new BigDecimal(OrderConstants.FREIGHT);
			
			List<CartPromotionGroup> cartPromotionGroups = cartShopGroup.getCartPromotionGroups();
			for (CartPromotionGroup cartPromotionGroup : cartPromotionGroups) {
				
				Rule rule = null;
				// 活动分组小计，用于计算满减
				double subPromotionGroupTotal = 0.0;
				
				List<CartMerchandise> cartMerchandises = cartPromotionGroup.getCartMerchandises();
				for (CartMerchandise cartMerchandise : cartMerchandises) {
					
					if(cartMerchandise.isSelect()){
						// 单价
						Double merchandisePrice = cartMerchandise.getMerchandisePrice();
						// 数量
						Integer merchandiseQty = cartMerchandise.getMerchandiseQty();
						// 小计
						double subTotal = merchandisePrice * merchandiseQty;
						
						rule = cartMerchandise.getRule();
						
						if(rule != null){
							Integer ruleType = rule.getRuleType();
							EnumPromotionType promotionType = EnumPromotionType.getPromotionType(ruleType);
							switch(promotionType){
							case FREE_SHIPPING:
								break;
							case FULL_CUT:
								break;
							case PRICE_DOWN:// 直降
								Double downAmount = rule.getRuleStraightDownAmount();
								merchandisePrice -= downAmount;
								subTotal = merchandisePrice * merchandiseQty;
								
								shopDiscountPrice = shopDiscountPrice.add(new BigDecimal(downAmount));
								break;
							}
						}
						
						subPromotionGroupTotal += subTotal;
						
						shopMerchandisesPrice = shopMerchandisesPrice.add(new BigDecimal(subTotal));
					}
				}
				
				Integer promotionType2 = cartPromotionGroup.getPromotionType();
				// 满减
				if(promotionType2 != null && promotionType2 != -1 && promotionType2 == 0 && rule != null){
					Double ruleTotalOver = rule.getRuleTotalOver();
					if(subPromotionGroupTotal >= ruleTotalOver){
						cartPromotionGroup.setMeetPromotionMsg(PromotionConstants.getPromotionMsg(ruleTotalOver, rule.getRuleDiscount()));
						shopDiscountPrice = shopDiscountPrice.add(new BigDecimal(rule.getRuleDiscount()));
						shopMerchandisesPrice = shopMerchandisesPrice.subtract(new BigDecimal(rule.getRuleDiscount()));
					}
				}
			}
			
			cartShopGroup.setTotalMerchandisePrice(shopMerchandisesPrice);
			cartShopGroup.setDiscountPrice(shopDiscountPrice);
			cartShopGroup.setFreightPrice(shopFreightPrice);
			cartShopGroup.setTotalPrice(shopMerchandisesPrice.add(shopFreightPrice));
			
			totalMerchandisesPrice = totalMerchandisesPrice.add(shopMerchandisesPrice);
			totalDiscountPrice = totalDiscountPrice.add(shopDiscountPrice);
			totalFreightPrice = totalFreightPrice.add(shopFreightPrice);
			totalPrice = totalPrice.add(shopMerchandisesPrice.add(shopFreightPrice));
		}
		
		cartDTO.setDiscountPrice(totalDiscountPrice);
		cartDTO.setTotalMerchandisePrice(totalMerchandisesPrice);
		cartDTO.setFreightPrice(totalFreightPrice);
		cartDTO.setTotalPrice(totalPrice);
		
	}
	
	private CartDTO setGroup(List<CartMerchandise> cartMerchandises){
		
		CartDTO cartDTO = new CartDTO();
		
		// 店铺分组
		Map<String, List<CartMerchandise>> shopMerchandiseMap = groupShops(cartMerchandises);
		
		// 活动分组后封装店铺分组
		List<CartShopGroup> groupPromotion = groupPromotion(shopMerchandiseMap);
		cartDTO.setCartShopGroups(groupPromotion);
		
		return cartDTO;
	}

	private List<CartShopGroup> groupPromotion(
			Map<String, List<CartMerchandise>> shopMerchandiseMap) {
		
		List<CartShopGroup> cartShopGroups = new ArrayList<CartShopGroup>(); 
		
		Iterator<Entry<String, List<CartMerchandise>>> it = shopMerchandiseMap.entrySet().iterator();
		while(it.hasNext()){
			
			Map<String, List<CartMerchandise>> promotionMerchandiseMap = new HashMap<String, List<CartMerchandise>>();
			Entry<String, List<CartMerchandise>> next = it.next();
			
			String key = next.getKey();
			List<CartMerchandise> value = next.getValue();
			
			for (CartMerchandise cartMerchandise : value) {
				CartPromotion cartPromotion = cartMerchandise.getCartPromotion();
				
				if(cartPromotion == null){
					List<CartMerchandise> list = promotionMerchandiseMap.get("-1");
					if(list == null){
						list = new ArrayList<CartMerchandise>();
						list.add(cartMerchandise);
						promotionMerchandiseMap.put("-1", list);
					}else{
						list.add(cartMerchandise);
					}
				}else{
					String promotionId = cartPromotion.getPromotionId();
					List<CartMerchandise> list = promotionMerchandiseMap.get(promotionId);
					
					if(list == null){
						list = new ArrayList<CartMerchandise>();
						list.add(cartMerchandise);
						promotionMerchandiseMap.put(promotionId, list);
					}else{
						list.add(cartMerchandise);
					}
				}
			}
			
			Iterator<Entry<String, List<CartMerchandise>>> iterator = promotionMerchandiseMap.entrySet().iterator();
			List<CartPromotionGroup> promotionGroups = new ArrayList<CartPromotionGroup>();
			while(iterator.hasNext()){
				Entry<String, List<CartMerchandise>> next2 = iterator.next();
				
				String key2 = next2.getKey();
				List<CartMerchandise> value2 = next2.getValue();
				
				CartPromotion cartPromotion = value2.get(0).getCartPromotion();
				Rule rule = value2.get(0).getRule();
				
				CartPromotionGroup cpg = new CartPromotionGroup();
				cpg.setCartMerchandises(value2);
				cpg.setPromotionId(key2);
				if(cartPromotion != null){
					cpg.setPromotionName(cartPromotion.getPromotionName());
				}
				if(rule != null){
					cpg.setPromotionType(rule.getRuleType());
				}
				
				promotionGroups.add(cpg);
			}
			
			CartShopGroup csg = new CartShopGroup();
			
			CartMerchandise cartMerchandise = value.get(0);
			
			csg.setShopId(key);
			csg.setShopName(cartMerchandise.getCartShop().getShopNameCn());
			csg.setCartPromotionGroups(promotionGroups);
			
			cartShopGroups.add(csg);
		}
		
		return cartShopGroups;
	}

	private Map<String, List<CartMerchandise>> groupShops(
			List<CartMerchandise> cartMerchandises) {
		Map<String, List<CartMerchandise>> shopMerchandiseMap = new HashMap<String, List<CartMerchandise>>();
		
		for (CartMerchandise cartMerchandise : cartMerchandises) {
		
			CartShop cartShop = cartMerchandise.getCartShop();
			String shopId = cartShop.getShopId();
			
			List<CartMerchandise> list = shopMerchandiseMap.get(shopId);
			
			if(list != null){
				list.add(cartMerchandise);
			}else{
				list = new ArrayList<CartMerchandise>();
				list.add(cartMerchandise);
				shopMerchandiseMap.put(shopId, list);
			}
		}
		return shopMerchandiseMap;
	}
	
	private void setPromotion(List<CartMerchandise> cartMerchandises){
		
		List<String> merchandiseIds = getMerchandiseIds(cartMerchandises);
		
		List<PromotionMerchandiseMapping> list = pmmService.findMappingByMerchandises(merchandiseIds);
		if(list == null || list.isEmpty()){
			log.info("PromotionMerchandiseMapping not found.");
			return;
		}
		
		List<String> promotionIds = getPromotionIds(list);
		
		Map<String, Promotion> promotionMap = promotionService.selectAvailabelByPromotionIds(promotionIds);
		if(promotionMap == null || promotionMap.isEmpty()){
			log.info("promotionMap not found.");
			return;
		}
		
		List<String> ruleIds = getRuleIds(promotionMap);
		
		Map<String, Rule> ruleMap = ruleService.selectByIds(ruleIds);
		if(ruleMap == null || ruleMap.isEmpty()){
			log.info("ruleMap not found.");
			return;
		}
		
		setPromotion(promotionMap, ruleMap, cartMerchandises, list);
		
	}
	
	private void setPromotion(Map<String, Promotion> promotionMap, Map<String, Rule> ruleMap, 
			List<CartMerchandise> cartMerchandises, List<PromotionMerchandiseMapping> list){
		
		for (CartMerchandise cartMerchandise : cartMerchandises) {
			String merchandiseId = cartMerchandise.getMerchandiseId();
			
			for (PromotionMerchandiseMapping promotionMerchandiseMapping : list) {
				String merchandiseId2 = promotionMerchandiseMapping.getMerchandiseId();
				
				if(merchandiseId.equals(merchandiseId2)){
					String promotionId = promotionMerchandiseMapping.getPromotionId();
					
					Promotion promotion = promotionMap.get(promotionId);
					
					CartPromotion cp = new CartPromotion();
					cp.setPromotionId(promotion.getPromotionId());
					cp.setPromotionName(promotion.getPromotionName());
					cp.setPromotionStart(promotion.getPromotionStart());
					cp.setPromotionEnd(promotion.getPromotionEnd());
					cp.setShopId(promotion.getRuleId());
					cp.setRuleId(promotion.getRuleId());
					
					cartMerchandise.setCartPromotion(cp);
					
					String ruleId = promotion.getRuleId();
					Rule rule = ruleMap.get(ruleId);
					cartMerchandise.setRule(rule);
					
					break;
				}
			}
		}
		
	}
	
	private int merchandisesQty(List<CartMerchandise> cartMerchandises,List<Boolean> isSelectList){
		int result = 0;
		for (CartMerchandise cartMerchandise : cartMerchandises) {
			boolean select = cartMerchandise.isSelect();
			if(isSelectList.contains(select)){
				result += cartMerchandise.getMerchandiseQty();
			}
		}
		
		return result;
	}
	
	private void setStock(List<CartMerchandise> cartMerchandises){
		
		List<String> merchandiseIds = getMerchandiseIds(cartMerchandises);
		
		Map<String, Stock> stockMap = getStock(merchandiseIds);
		
		for (CartMerchandise cartMerchandise : cartMerchandises) {
			String merchandiseId = cartMerchandise.getMerchandiseId();
			
			if(stockMap == null || stockMap.get(merchandiseId) == null){
				log.info("stockMap or stock is null.");
				cartMerchandise.setMerchandiseQty(CommonConstant.NUMBER_0);
				cartMerchandise.setMerchandiseStockQty(CommonConstant.NUMBER_0);
				continue;
			}
			
			Stock stock = stockMap.get(merchandiseId);
			
			Integer stockQty = stock.getStockQty();
			Integer stockPreSubQty = stock.getStockPreSubQty();
			Integer merchandiseQty = cartMerchandise.getMerchandiseQty();
			stockQty -= stockPreSubQty;
			
			if(merchandiseQty > stockQty){
				cartMerchandise.setMerchandiseQty(stockQty);
			}
			
			cartMerchandise.setMerchandiseStockQty(stockQty);
		}
	}
	
	private void setShop(List<CartMerchandise> cartMerchandises){
		
		List<String> merchandiseIds = getMerchandiseIds(cartMerchandises);
		List<Merchandise> merchandises = merchandiseService.findMerchandiseByIds(merchandiseIds);
		
		List<String> shopIds = getShopIds(merchandises);
		Map<String, Shop> shopMap = shopService.findShopsByIds(shopIds);
		
		for (Merchandise merchandise : merchandises) {
			
			String merchandiseId = merchandise.getMerchandiseId();
			
			for (CartMerchandise cartMerchandise : cartMerchandises) {
				String cartMerchandiseId = cartMerchandise.getMerchandiseId();
				if(merchandiseId.equals(cartMerchandiseId)){
					Shop shop = shopMap.get(merchandise.getShopId());
					
					CartShop cs = new CartShop();
					cs.setShopId(shop.getShopId());
					cs.setShopNameCn(shop.getShopNameCn());
					
					cartMerchandise.setCartShop(cs);
				}
			}
		}
	}
	
	private List<String> getShopIds(List<Merchandise> merchandises){
		
		List<String> shopIds = new ArrayList<String>();
		
		for (Merchandise merchandise : merchandises) {
			
			shopIds.add(merchandise.getShopId());
		}
		
		return shopIds;
	}
	
	private List<String> getMerchandiseIds(List<CartMerchandise> cartMerchandises){
		
		List<String> merchandiseIds = new ArrayList<String>();
		
		for (CartMerchandise cartMerchandise : cartMerchandises) {
			String merchandiseId = cartMerchandise.getMerchandiseId();
			
			merchandiseIds.add(merchandiseId);
		}
		
		return merchandiseIds;
	}
	
	private List<String> getPromotionIds(List<PromotionMerchandiseMapping> list){
		
		List<String> promotionIds = new ArrayList<String>();
		
		for (PromotionMerchandiseMapping pmm : list) {
			String promotionId = pmm.getPromotionId();
			
			promotionIds.add(promotionId);
		}
		
		return promotionIds;
	}
	
	private List<String> getRuleIds(Map<String, Promotion> promotionMap){
		
		List<String> ruleIds = new ArrayList<String>();
		
		Iterator<Entry<String, Promotion>> iterator = promotionMap.entrySet().iterator();
		while(iterator.hasNext()){
			Entry<String, Promotion> next = iterator.next();
			Promotion value = next.getValue();
			ruleIds.add(value.getRuleId());
		}
		
		return ruleIds;
	}

	/**
	 * 改变购物车商品的选中状态
	 */
	public int select(User user, List<String> merchandiseIds) {
		// Redis key
		String cartKey = CartConstants.cartKey(user);
		log.info("cart key:"+cartKey);
		
		// 获取当前购物车信息
		List<CartMerchandise> cartMerchandises = (List<CartMerchandise>)JedisManager.getObject(cartKey);
		if(cartMerchandises == null || cartMerchandises.isEmpty()){
			throw new BadRequestException("no data in redis.change select failed.");
		}
		
		changeSelect(cartMerchandises, merchandiseIds);
		
		// 放入缓存
		log.info("end to execute select.set to redis.");
		JedisManager.setObject(cartKey, CartConstants.CART_OUT_TIME, cartMerchandises);
		
		return CommonConstant.NUMBER_1;
	}
	
	private void changeSelect(List<CartMerchandise> cartMerchandises, List<String> merchandiseIds){
		for (CartMerchandise cartMerchandise : cartMerchandises) {
			String merchandiseId = cartMerchandise.getMerchandiseId();
			if(merchandiseIds.contains(merchandiseId)){
				cartMerchandise.setSelect(true);
			}else{
				cartMerchandise.setSelect(false);
			}
		}
	}

	/**
	 * 结算
	 */
	public CartDTO settlement(User user, List<String> merchandiseIds) {
		// Redis key
		String cartKey = CartConstants.cartKey(user);
		log.info("cart key:"+cartKey);
		
		// 获取当前购物车信息
		List<CartMerchandise> cartMerchandises = (List<CartMerchandise>)JedisManager.getObject(cartKey);
		if(cartMerchandises == null || cartMerchandises.isEmpty()){
			log.info("no data in redis.");
			return null;
		}
		
		// 获取需要结算的商品信息
		List<CartMerchandise> newCartMerchandises = findByIds(cartMerchandises, merchandiseIds);
		if(newCartMerchandises == null || newCartMerchandises.isEmpty()){
			log.info("merchandise not found for settlement.merchandiseIds:{}",merchandiseIds);
			return null;
		}
		
		// 库存信息
		setStock(newCartMerchandises);
		
		// 店铺信息
		setShop(newCartMerchandises);
		
		// 活动信息
		setPromotion(newCartMerchandises);
		
		// 分组
		CartDTO cartDTO = setGroup(newCartMerchandises);
		
		// 设置价格
		setPrice(cartDTO);
		
		return cartDTO;
	}
	
	private List<CartMerchandise> findByIds(List<CartMerchandise> cartMerchandises, 
			List<String> merchandiseIds){
		List<CartMerchandise> newCartMerchandises = new ArrayList<CartMerchandise>();
		
		for (CartMerchandise cartMerchandise : cartMerchandises) {
			String merchandiseId = cartMerchandise.getMerchandiseId();
			if(merchandiseIds.contains(merchandiseId)){
				if(!cartMerchandise.isSelect()){
					cartMerchandise.setSelect(true);
				}
				newCartMerchandises.add(cartMerchandise);
			}
		}
		return newCartMerchandises;
	}
}
